feat: add configurable field-level restrictions for container and pod overrides#1653
Conversation
|
Warning Review limit reached
More reviews will be available in 3 minutes and 7 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughIntroduces a configurable ChangesConfigurable Override Field Restriction
Sequence Diagram(s)sequenceDiagram
rect rgba(70, 130, 180, 0.5)
Note over Reconcile,ApplyContainerOverrides: Container override path
Reconcile->>GetKubeContainersFromDevfile: GetRestrictedContainerOverrideFields
GetKubeContainersFromDevfile->>ApplyContainerOverrides: restrictedFields
ApplyContainerOverrides->>restrictContainerOverride: override, restrictedFields
restrictContainerOverride-->>ApplyContainerOverrides: error or nil
end
rect rgba(60, 179, 113, 0.5)
Note over ProvisionStorage,GetVolumesFromOverrides: Pod override and storage path
ProvisionStorage->>rewriteContainerVolumeMounts: GetRestrictedPodOverrideFields
rewriteContainerVolumeMounts->>GetVolumesFromOverrides: workspace, restrictedFields
GetVolumesFromOverrides->>restrictPodOverride: &override.Spec, restrictedFields
restrictPodOverride-->>ProvisionStorage: error or nil
end
Estimated code review effort🎯 5 (Critical) | ⏱️ ~130 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hi! I'm che-ai-assistant — I help with your pull requests. Available commands:
|
| return err | ||
| } | ||
| } | ||
| if err := rules.checkString("terminationMessagePath", &override.TerminationMessagePath); err != nil { |
There was a problem hiding this comment.
For container_restrictions.go and pod_restriction.go, I am a bit concerned because we are calling checkString(<field>) for so many container/pod fields.
Have you considered iterating over the fields in DeniedContainerOverrideFields and DeniedPodOverrideFields and checking if those fields exist in the container/pod instead?
Please correct me if I'm wrong but it seems like this PR is checking this the other way around (going over all possible container/pod fields, and checking DeniedContainerOverrideFields/DeniedPodOverrideFields)
There was a problem hiding this comment.
Have you considered iterating over the fields in DeniedContainerOverrideFields and DeniedPodOverrideFields and checking if those fields exist in the container/pod instead?
It is a way complicated
… overrides Signed-off-by: Anatolii Bazko <abazko@redhat.com>
fd4d54f to
73a202d
Compare
… overrides Signed-off-by: Anatolii Bazko <abazko@redhat.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1653 +/- ##
==========================================
+ Coverage 37.17% 40.52% +3.34%
==========================================
Files 168 171 +3
Lines 14761 15621 +860
==========================================
+ Hits 5488 6330 +842
+ Misses 8921 8906 -15
- Partials 352 385 +33 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
… overrides Signed-off-by: Anatolii Bazko <abazko@redhat.com>
… overrides Signed-off-by: Anatolii Bazko <abazko@redhat.com>
|
/che-ai-assistant ok-pr-review Review is complete. Please check the review comments below. |
tolusha
left a comment
There was a problem hiding this comment.
Code Review Summary
Overall Assessment: Solid implementation of a security-critical feature with excellent test coverage. The restriction system is well-architected with proper defense-in-depth.
Key Highlights:
✅ 2700+ lines of comprehensive test coverage
✅ Security-first Kubernetes defaults aligned with Pod Security Standards
✅ Clean FieldRestriction abstraction with typed check methods
✅ Platform awareness (K8s vs OpenShift defaults)
✅ Defense-in-depth with always-restricted + configurable fields
Primary Concern: Breaking behavioral change on Kubernetes requires release notes and migration guide before merge (see inline comment on defaults.go).
The inline comments below provide specific suggestions for improvements.
| RestrictedPodOverrideFields: []string{}, | ||
| } | ||
| defaultKubernetesOverrideConfig = &v1alpha1.OverrideConfig{ | ||
| RestrictedContainerOverrideFields: []string{ |
There was a problem hiding this comment.
Breaking change: Release notes and migration guide required
The new Kubernetes default restrictions will cause existing DevWorkspaces using security-sensitive overrides to fail after operator upgrade. Any workspace with securityContext.privileged=true, hostNetwork=true, or volumes.hostPath will fail to start.
Required before merge:
- Release notes documenting this breaking change
- Migration guide with two paths:
- Set
restrictedContainerOverrideFields: []andrestrictedPodOverrideFields: []in DevWorkspaceOperatorConfig to restore pre-upgrade behavior - Remove restricted overrides from DevWorkspaces before upgrade
- Set
- Consider logging a warning when a workspace fails due to new default restrictions
| return checkContainerSecurityContext(override.SecurityContext, remaining, restriction) | ||
| } | ||
|
|
||
| return nil |
There was a problem hiding this comment.
Can we add a log message in the cases where the root/remaining is not matched by the case statements?
| return checkContainerResourceClaims(resources.Claims, remaining, restriction) | ||
| } | ||
|
|
||
| return nil |
There was a problem hiding this comment.
Can we add a log message in the cases where the root/remaining is not matched by the case statements?
dkwon17
left a comment
There was a problem hiding this comment.
Tested and LGTM, just a comment
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: btjd, tolusha The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
| func checkContainer(override *corev1.Container, root string, remaining string, restriction *FieldRestriction) error { | ||
| if remaining == "" { | ||
| switch root { | ||
| case "workingDir": |
There was a problem hiding this comment.
Something to consider for the future:
This implementation requires manual synchronization with Kubernetes API changes. For example, if a future Kubernetes release adds a new field to corev1.Container or corev1.SecurityContext, it won't be evaluated by these restriction checks until this code is updated.
It might be worth exploring ways to make such cases easier to detect in tests.
| Override: corev1.PodSpec{Volumes: []corev1.Volume{{Name: "vol", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}}}}, | ||
| RestrictedFields: []string{"volumes.hostPath"}, | ||
| IsErrorExpected: false, | ||
| }, |
There was a problem hiding this comment.
For future, We might want to add more cases here.
volumeSourceType() maps 20+ volume types
devworkspace-operator/pkg/library/overrides/pod_restrictions.go
Lines 351 to 371 in af782ad
|
Tested on Kubernetes (minikube) and OpenShift (CRC) with various combination and it seems to be working well ✅ Always-Restricted Fields (regardless of config)
Platform Defaults (no DWOC config required)
Custom Restriction Lists via DWOC
Per-Workspace DWOC (
|
| Scenario | Kubernetes | OpenShift |
|---|---|---|
Custom list ["workingDir"] — workingDir |
Expected: Denied | Expected: Denied |
Custom list ["workingDir"] — privileged=true (not in list) |
Expected: Allowed | Expected: Allowed |
No overrides field — privileged=true (inherits cluster defaults) |
Expected: Denied | Expected: Allowed |
Nested Field Restrictions via DWOC
| Scenario | Kubernetes | OpenShift |
|---|---|---|
["envFrom.secretRef"] — envFrom.secretRef |
Expected: Denied | Expected: Denied |
["envFrom.secretRef"] — envFrom.configMapRef |
Expected: Allowed | Expected: Allowed |
["volumes.hostPath"] — volumes.hostPath |
Expected: Denied | Expected: Denied |
["volumes.hostPath"] — volumes.emptyDir |
Expected: Allowed | Expected: Allowed |
["securityContext.runAsUser=0"] — runAsUser: 0 (pod) |
Expected: Denied | Expected: Denied |
["securityContext.runAsUser=0"] — runAsUser: 1000 (pod) |
Expected: Allowed | Expected: Allowed |
What does this PR do?
This PR adds a configurable restriction system for
container-overridesandpod-overridesDevWorkspace attributes. Cluster admins can define deny rules in DevWorkspaceOperatorConfig to block specific fields (e.g.hostNetwork, securityContext.privileged) or specific values (e.g. restartPolicy=Always) from being set via overrides. On Kubernetes, security-sensitive defaults are denied out of the box — such as privileged containers,
running as root, host networking, and hostPath volumes — to match the restrictions that OpenShift enforces natively via SCCs
What issues does this PR fix or reference?
N/A
Is it tested? How?
Create a DevWorkspace with
container-overrides, for instance:PR Checklist
/test v8-devworkspace-operator-e2e, v8-che-happy-pathto trigger)v8-devworkspace-operator-e2e: DevWorkspace e2e testv8-che-happy-path: Happy path for verification integration with CheSummary by CodeRabbit
Release Notes
New Features
container-overridesandpod-overrides.DevWorkspaceOperatorConfig.spec.config.overrides, withrestrictedContainerOverrideFieldsandrestrictedPodOverrideFields.Documentation